<template>
  <div class="element-positopn-panel">
    <div class="title tit2">{{ $t('position.layer') }}：</div>
    <ButtonGroup class="row cengji_sty duiqi_sty">
      <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.TOP)">
        <IconSendToBack class="btn-icon" />
        <div class="txt_sty">{{ $t('position.top') }}</div>
      </Button>
      <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.BOTTOM)">
        <IconBringToFrontOne class="btn-icon" />
        <div class="txt_sty">{{ $t('position.bottom') }}</div>
      </Button>
      <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.UP)">
        <IconBringToFront class="btn-icon" />
        <div class="txt_sty">{{ $t('position.up') }}</div>
      </Button>
      <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.DOWN)">
        <IconSentToBack class="btn-icon" />
        <div class="txt_sty">{{ $t('position.down') }}</div>
      </Button>
    </ButtonGroup>
    
    <div class="title">{{ $t('position.align') }}：</div>
    <ButtonGroup class="row duiqi_sty">
      <Button style="flex: 1;" v-tooltip="$t('position.alignLeft')" @click="alignElementToCanvas(ElementAlignCommands.LEFT)"><IconAlignLeft /></Button>
      <Button style="flex: 1;" v-tooltip="$t('position.alignHorizontal')" @click="alignElementToCanvas(ElementAlignCommands.HORIZONTAL)"><IconAlignVertically /></Button>
      <Button style="flex: 1;" v-tooltip="$t('position.alignRight')" @click="alignElementToCanvas(ElementAlignCommands.RIGHT)"><IconAlignRight /></Button>
      <Button style="flex: 1;" v-tooltip="$t('position.alignTop')" @click="alignElementToCanvas(ElementAlignCommands.TOP)"><IconAlignTop /></Button>
      <Button style="flex: 1;" v-tooltip="$t('position.alignVertical')" @click="alignElementToCanvas(ElementAlignCommands.VERTICAL)"><IconAlignHorizontally /></Button>
      <Button style="flex: 1;" v-tooltip="$t('position.alignBottom')" @click="alignElementToCanvas(ElementAlignCommands.BOTTOM)"><IconAlignBottom /></Button>
    </ButtonGroup>

    <div class="title">{{ $t('position.position') }}：</div>
    <div class="row weizhi_sty">
      <div class="item_sty">
        <div class="label">{{ $t('position.horizontal') }}</div>
        <NumberInput
          :step="5"
          :value="left"
          @update:value="value => updateLeft(value)"
          style="width: 70%;"
        />
      </div>
      <div class="item_sty">
        <div class="label">{{ $t('position.vertical') }}</div>
        <NumberInput
          :step="5"
          :value="top"
          @update:value="value => updateTop(value)"
          style="width: 70%;"
        />
      </div>
    </div>
    <template v-if="handleElement!.type !== 'line'">
      <div class="row weizhi_sty">
        <div class="item_sty">
          <div class="label">{{ $t('position.width') }}</div>
          <NumberInput
            :min="minSize"
            :max="1500"
            :step="5"
            :disabled="isVerticalText"
            :value="width"
            @update:value="value => updateWidth(value)"
            style="width: 70%;"
          />
        </div>
        <template v-if="['image', 'shape', 'audio'].includes(handleElement!.type)">
          <IconLock style="width: 10%;" class="icon-btn active" v-tooltip="$t('position.unlockRatio') " @click="updateFixedRatio(false)" v-if="fixedRatio" />
          <IconUnlock style="width: 10%;" class="icon-btn" v-tooltip="$t('position.lockRatio') " @click="updateFixedRatio(true)" v-else />
        </template>
        <div style="width: 0%;" v-else></div>
        <div class="item_sty">
          <div class="label">{{ $t('position.height') }}</div>
          <NumberInput 
            :min="minSize"
            :max="800"
            :step="5"
            :disabled="isHorizontalText || handleElement!.type === 'table'" 
            :value="height" 
            @update:value="value => updateHeight(value)"
            style="width: 70%;"
          />
        </div>
      </div>
    </template>

    <template v-if="!['line', 'video', 'audio'].includes(handleElement!.type)">
      <div class="row weizhi_sty">
        <div class="item_sty" style="flex: 1;">
          <div class="label">{{ $t('position.rotate') }}</div>
          <NumberInput 
            :min="-180"
            :max="180"
            :step="5"
            :value="rotate" 
            @update:value="value => updateRotate(value)" 
            style="width: 70%;" 
          />
        </div>
        <div class="text-btn" @click="updateRotate45('-')" style="width: 24%;"><IconRotate /> {{ $t('position.rotateMinus45') }}</div>
        <div class="text-btn" @click="updateRotate45('+')"  style="width: 24%;"><IconRotate :style="{ transform: 'rotateY(180deg)' }" /> {{ $t('position.rotatePlus45') }}</div>
      </div>
    </template>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import { round } from 'lodash'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import type { PPTElement } from '@/types/slides'
import { ElementAlignCommands, ElementOrderCommands } from '@/types/edit'
import { MIN_SIZE } from '@/configs/element'
import { SHAPE_PATH_FORMULAS } from '@/configs/shapes'
import useOrderElement from '@/hooks/useOrderElement'
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import Divider from '@/components/Divider.vue'
import Button from '@/components/Button.vue'
import ButtonGroup from '@/components/ButtonGroup.vue'
import NumberInput from '@/components/NumberInput.vue'

const slidesStore = useSlidesStore()
const { handleElement, handleElementId } = storeToRefs(useMainStore())

const left = ref(0)
const top = ref(0)
const width = ref(0)
const height = ref(0)
const rotate = ref(0)
const fixedRatio = ref(false)

const minSize = computed(() => {
  if (!handleElement.value) return 20
  return MIN_SIZE[handleElement.value.type] || 20
})

const isHorizontalText = computed(() => {
  return handleElement.value?.type === 'text' && !handleElement.value.vertical
})
const isVerticalText = computed(() => {
  return handleElement.value?.type === 'text' && handleElement.value.vertical
})

watch(handleElement, () => {
  if (!handleElement.value) return

  left.value = round(handleElement.value.left, 1)
  top.value = round(handleElement.value.top, 1)

  fixedRatio.value = 'fixedRatio' in handleElement.value && !!handleElement.value.fixedRatio

  if (handleElement.value.type !== 'line') {
    width.value = round(handleElement.value.width, 1)
    height.value = round(handleElement.value.height, 1)
    rotate.value = 'rotate' in handleElement.value && handleElement.value.rotate !== undefined ? round(handleElement.value.rotate, 1) : 0
  }
}, { deep: true, immediate: true })

const { orderElement } = useOrderElement()
const { alignElementToCanvas } = useAlignElementToCanvas()

const { addHistorySnapshot } = useHistorySnapshot()

// 设置元素位置
const updateLeft = (value: number) => {
  const props = { left: value }
  slidesStore.updateElement({ id: handleElementId.value, props })
  addHistorySnapshot()
}
const updateTop = (value: number) => {
  const props = { top: value }
  slidesStore.updateElement({ id: handleElementId.value, props })
  addHistorySnapshot()
}

// 设置元素宽度、高度、旋转角度
// 对形状设置宽高时，需要检查是否需要更新形状路径
const updateShapePathData = (width: number, height: number) => {
  if (handleElement.value && handleElement.value.type === 'shape' && 'pathFormula' in handleElement.value && handleElement.value.pathFormula) {
    const pathFormula = SHAPE_PATH_FORMULAS[handleElement.value.pathFormula]

    let path = ''
    if ('editable' in pathFormula && pathFormula.editable) path = pathFormula.formula(width, height, handleElement.value.keypoints!)
    else path = pathFormula.formula(width, height)

    return {
      viewBox: [width, height],
      path,
    }
  }
  return null
}

const updateWidth = (value: number) => {
  if (!handleElement.value) return
  if (handleElement.value.type === 'line' || isVerticalText.value) return

  let h = height.value

  if (fixedRatio.value) {
    const ratio = width.value / height.value
    h = (value / ratio) < minSize.value ? minSize.value : (value / ratio)
  }
  let props: Partial<PPTElement> = { width: value, height: h }

  const shapePathData = updateShapePathData(value, h)
  if (shapePathData) {
    props = {
      width: value,
      height: h,
      ...shapePathData,
    }
  }

  slidesStore.updateElement({ id: handleElementId.value, props })
  addHistorySnapshot()
}

const updateHeight = (value: number) => {
  if (!handleElement.value) return
  if (handleElement.value.type === 'line' || handleElement.value.type === 'table' || isHorizontalText.value) return

  let w = width.value

  if (fixedRatio.value) {
    const ratio = width.value / height.value
    w = (value * ratio) < minSize.value ? minSize.value : (value * ratio)
  }
  let props: Partial<PPTElement> = { width: w, height: value }

  const shapePathData = updateShapePathData(w, value)
  if (shapePathData) {
    props = {
      width: w,
      height: value,
      ...shapePathData,
    }
  }

  slidesStore.updateElement({ id: handleElementId.value, props })
  addHistorySnapshot()
}

const updateRotate = (value: number) => {
  const props = { rotate: value }
  slidesStore.updateElement({ id: handleElementId.value, props })
  addHistorySnapshot()
}

// 固定元素的宽高比
const updateFixedRatio = (value: boolean) => {
  const props = { fixedRatio: value }
  slidesStore.updateElement({ id: handleElementId.value, props })
  addHistorySnapshot()
}

// 将元素旋转45度（顺时针或逆时针）
const updateRotate45 = (command: '+' | '-') => {
  let _rotate = Math.floor(rotate.value / 45) * 45
  if (command === '+') _rotate = _rotate + 45
  else if (command === '-') _rotate = _rotate - 45

  if (_rotate < -180) _rotate = -180
  if (_rotate > 180) _rotate = 180

  const props = { rotate: _rotate }
  slidesStore.updateElement({ id: handleElementId.value, props })
  addHistorySnapshot()
}
</script>

<style lang="scss" scoped>
.element-positopn-panel{
    .tit2{
        margin-top: 8px !important;
        margin-bottom: 24px !important;
    }
    .title{
        font-size: 12px;
        color: #999999;
        margin: 20px 0;
    }
    .cengji_sty{
        .button{
            position: relative;
            font-size: 12px;
            color: #333;
            .txt_sty{
                position: absolute;
                top: -32px;
                left: 50%;
                transform: translateX(-50%);
            }
        }
    }
    .duiqi_sty{
        border-radius: 8px;
        border: 1px solid #F2F2F2;
        .button{
            padding: 0;
            height: 40px;
            line-height: 40px;
            border: none;
            &:first-child{
                border-top-left-radius: 8px !important;
                border-bottom-left-radius: 8px !important;
            }
            &:last-child{
                border-top-right-radius: 8px !important;
                border-bottom-right-radius: 8px !important;
            }
        }
    }
    .weizhi_sty{
      .item_sty{
        display: flex;
        align-items: center;
        .label{
          font-size: 12px;
          color: #333333;
          margin-right: 5px;
        }
        .number-input{
          border-radius: 8px;
          border: 1px solid #F2F2F2;
          padding: 0;
        }
      } 
    }
}
.row {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
// .title {
//   margin-bottom: 10px;
// }
.label {
  text-align: center;
}
.btn-icon {
  margin-right: 3px;
}
.icon-btn {
  cursor: pointer;

  &.active {
    color: $themeColor;
  }
}
.text-btn {
  height: 30px;
  line-height: 30px;
  text-align: center;
  cursor: pointer;

  &:hover {
    background-color: #efefef;
    border-radius: $borderRadius;
  }
}
</style>
<style lang="scss">
.item_sty{
  .number-input{
    input{
      border-top-right-radius: 8px;
      border-bottom-right-radius: 8px;
    }
  }
}
</style>